package com.flyqiu.common.property;

import com.flyqiu.common.std.FlyQiuBooleanFun;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * 使用 Java 反射 Field 来实现属性访问。
 * <p>
 * 此类提供了对 Java 属性的读取和写入操作。
 */
public class FlyQiuFieldProperty implements FlyQiuBaseProperty {

    private final Field field;
    private final boolean read;
    private final boolean write;

    /**
     * 构造一个新的 FlyQiuFieldProperty 对象。
     *
     * @param field 属性字段
     */
    public FlyQiuFieldProperty(Field field) {
        this.field = field;
        field.setAccessible(true);

        // 判断字段是否可读
        this.read = !field.isSynthetic();

        // 判断字段是否可写
        this.write = !field.isSynthetic() && !Modifier.isFinal(field.getModifiers());
    }

    /**
     * 判断属性是否可读。
     *
     * @return 如果属性可读，则返回 true；否则返回 false
     */
    @Override
    public boolean isRead() {
        return read;
    }

    /**
     * 判断属性是否可写。
     *
     * @return 如果属性可写，则返回 true；否则返回 false
     */
    @Override
    public boolean isWrite() {

        return write;
    }

    /**
     * 判断属性是否为静态属性。
     *
     * @return 如果属性为静态属性，则返回 true；否则返回 false
     */
    @Override
    public boolean isStatic() {
        return Modifier.isStatic(field.getModifiers());
    }

    /**
     * 获取属性的名称。
     *
     * @return 属性名称
     */
    @Override
    public String getName() {
        return field.getName();
    }

    /**
     * 获取属性的数据类型。
     *
     * @return 属性的数据类型
     */
    @Override
    public Class<?> getType() {
        return field.getType();
    }

    @Override
    public <T extends Annotation> List<T> getAnnotations(FlyQiuBooleanFun<Annotation> filter, Function<Annotation, T> valueMapper) {
        if (filter == null) {
            throw new NullPointerException("filter cannot be null");
        }
        if (valueMapper == null) {
            throw new NullPointerException("filter cannot be null");
        }
        Annotation[] annotations = field.getAnnotations();
        List<T> result = new ArrayList<>();
        for (Annotation annotation : annotations) {
            if (!filter.apply(annotation)) {
                continue;
            }
            result.add(valueMapper.apply(annotation));
        }
        return result;
    }

    /**
     * 获取属性的值。
     *
     * @param obj 对象实例
     * @return 属性的值
     * @throws IllegalStateException 如果属性不可读
     */
    @Override
    public Object getValue(Object obj) {
        if (!read) {
            throw new IllegalStateException("Field '" + getName() + "' in class " + obj.getClass().getName() + " is not readable");
        }
        try {
            return field.get(obj);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Error getting value for field '" + getName() + "'", e);
        }
    }

    /**
     * 设置属性的值。
     *
     * @param obj 对象实例
     * @param val 属性的新值
     * @throws IllegalStateException 如果属性不可写
     */
    @Override
    public void setValue(Object obj, Object val) {
        if (!write) {
            throw new IllegalStateException("Field '" + getName() + "' in class " + obj.getClass().getName() + " is not writable");
        }
        try {
            field.set(obj, val);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Error setting value for field '" + getName() + "'", e);
        }
    }
}
